package com.service.impl;

import cn.hutool.crypto.digest.BCrypt;
import com.alibaba.fastjson2.JSONObject;
import com.constant.PosConstant;
import com.domain.entity.User;
import com.domain.req.*;
import com.exception.ServiceException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mapper.CartMapper;
import com.mapper.UserMapper;
import com.service.UserService;
import com.utils.JWTUtils;
import com.utils.ValidatorUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @author caishenao
 * @description 针对表【user】的数据库操作Service实现
 * @createDate 2023-10-12 20:12:53
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private CartMapper cartMapper;

    /**
     * 注册用户
     *
     * @param registerReq 注册请求
     */
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterReq registerReq) {
        log.info("访问注册用户接口,请求入参:{}", JSONObject.toJSONString(registerReq));
        // 1. 注解校验
        ValidatorUtils.validateEntity(registerReq);

        // 2. 判断账户是否已经存在
        User user = userMapper.selectByUserName(registerReq.getUserName());
        if (user != null) {
            // 账户已经存在了
            log.error("账户:{}已存在，无法注册,存在的用户信息:{}", registerReq.getUserName(), JSONObject.toJSONString(user));
            throw new ServiceException("账户已存在，无法注册!");
        }

        // 3. 转换为用户
        User saveUser = registerReqConversion(registerReq);
        userMapper.insert(saveUser);
    }

    /**
     * 将注册请求转换为user对象
     *
     * @param registerReq 注册请求
     * @return 用户对象
     */
    private User registerReqConversion(RegisterReq registerReq) {
        User user = new User();
        user.setEmail(registerReq.getEmail());
        user.setUserName(registerReq.getUserName());
        user.setPhone(registerReq.getPhone());
        user.setPos(PosConstant.ORDINARY);
        user.setRegistration(new Date());
        String pwd = registerReq.getPwd();
        user.setPwd(BCrypt.hashpw(pwd));
        user.setName(registerReq.getName());
        user.setAvatar(registerReq.getAvatar());
        user.setBalance(BigDecimal.ZERO);
        return user;
    }

    /***
     * 用户登录并返回生成的token
     *
     * @param loginReq 登录请求
     * @return 登录用户生成的token
     */
    @Override
    public String login(LoginReq loginReq) {
        log.info("访问用户登录接口,请求入参:{}", JSONObject.toJSONString(loginReq));

        // 1. 注解校验
        ValidatorUtils.validateEntity(loginReq);

        // 2. 根据账户查询登录的用户
        User user = userMapper.selectByUserName(loginReq.getUserName());
        if (user == null) {
            // 用户不存在
            throw new ServiceException("账户不存在！");
        }

        // 3. 存在，比较密码
        if (!BCrypt.checkpw(loginReq.getPwd(), user.getPwd())) {
            // 密码不正确
            throw new ServiceException("密码不正确！");
        }

        // 4. 生成对应的token
        String token = JWTUtils.createToken(user);
        log.info("访问用户登录接口,请求出参:{}", token);
        return token;
    }

    /**
     * 分页查询用户信息
     *
     * @param pageReq 分页请求
     * @param user    用户信息
     */
    @Override
    public PageInfo<User> pageList(PageReq pageReq, User user) {
        log.info("访问分页查询用户信息接口，请求入参:pageReq{};user:{}", JSONObject.toJSONString(pageReq), JSONObject.toJSONString(user));

        //初始化
        PageHelper.startPage(pageReq.getPageNum(), pageReq.getPageSize());
        List<User> list = userMapper.list(user);
        PageInfo<User> userPageInfo = new PageInfo<>(list);
        log.info("访问分页查询用户信息接口，请求返参:{}", JSONObject.toJSONString(userPageInfo));
        return userPageInfo;
    }

    /**
     * 判断当前用户为管理员
     *
     * @return true:管理员;false:普通用户
     */
    @Override
    public Boolean isAdmin() {
        // 1. 获取当前登录用户
        User currentUser = JWTUtils.getCurrentUser();
        if (currentUser == null) {
            // 当前没登陆，返回false
            return false;
        }
        return PosConstant.ADMIN.equals(currentUser.getPos());
    }

    /**
     * 获取当前用户
     *
     * @return 用户信息
     */
    @Override
    public User info() {
        // 1. 获取当前登录用户
        User currentUser = JWTUtils.getCurrentUser();

        // 2. 查询当前用户信息是否被删除
        return userMapper.getById(currentUser.getId());
    }

    /**
     * 根据id删除用户
     *
     * @param id 用户id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Integer id) {
        // 1. 根据用户id查询用户信息
        User user = userMapper.getById(id);

        // 2. 判断数据是否存在
        if (user == null) {
            log.error("用户信息不存在！");
            throw new ServiceException("用户信息不存在！");
        }

        // 3. 根据用户id删除用户的购物车信息
        cartMapper.deleteByUserId(id);

        // 4. 删除用户信息
        userMapper.deleteById(id);
    }

    /**
     * 修改用户信息
     *
     * @param userUpdateReq 用户信息修改
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateById(UserUpdateReq userUpdateReq) {
        // 1. 注解校验
        ValidatorUtils.validateEntity(userUpdateReq);

        // 2. 判断权限修改
        if (StringUtils.isNotBlank(userUpdateReq.getPos()) && !isAdmin()) {
            // 权限不为空，并且不是管理员
            log.error("权限不足，无法修改!");
            throw new ServiceException("权限不足，无法修改!");
        }

        // 3. 转换为用户对象
        User user = userUpdateReqConversion(userUpdateReq);

        // 4. 修改数据库
        userMapper.updateBySelect(user);
    }

    /**
     * 修改密码
     *
     * @param changePasswordReq 要修改的密码请求
     */
    @Override
    public void changePassword(ChangePasswordReq changePasswordReq) {
        // 1. 数据校验
        ValidatorUtils.validateEntity(changePasswordReq);

        // 2. 判断旧密码是否相同
        User currentUser = JWTUtils.getCurrentUser();
        if (!BCrypt.checkpw(changePasswordReq.getOldPwd(), currentUser.getPwd())) {
            // 旧密码不相同
            log.error("旧密码不同!");
            throw new ServiceException("旧密码不相同,无法修改!");
        }

        // 3. 存储新密码
        User user = new User();
        user.setId(currentUser.getId());
        user.setPwd(BCrypt.hashpw(changePasswordReq.getNewPwd()));
        userMapper.updateBySelect(user);
    }

    /**
     * 为用户充值
     *
     * @param rechargeReq 充值请求
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recharge(RechargeReq rechargeReq) {
        // 1. 数据校验
        ValidatorUtils.validateEntity(rechargeReq);

        // 2. 判断充值的用户是否存在
        User user = userMapper.getById(rechargeReq.getId());
        if (user == null) {
            // 充值的用户不存在
            log.error("id为:{}的用户不存在,无法充值!", JSONObject.toJSONString(rechargeReq.getId()));
            throw new ServiceException("用户不存在,无法充值!");
        }

        // 3. 对金额进行相加，并设置进用户
        BigDecimal balance = user.getBalance();
        balance = balance.add(rechargeReq.getBalance());
        user.setBalance(balance);

        // 4. 更新用户信息
        userMapper.updateBySelect(user);
    }

    /**
     * 根据用户id查询用户信息
     *
     * @param id 用户id
     * @return 用户信息
     */
    @Override
    public User getUserById(Integer id) {
        User user = userMapper.getUserById(id);
        return user;
    }

    /**
     * 用户请求转换为用户信息
     *
     * @param userUpdateReq 用户请求
     * @return 用户信息
     */
    private User userUpdateReqConversion(UserUpdateReq userUpdateReq) {
        User user = new User();
        user.setId(userUpdateReq.getId());
        user.setEmail(userUpdateReq.getEmail());
        user.setPhone(userUpdateReq.getPhone());
        user.setPos(userUpdateReq.getPos());
        user.setName(userUpdateReq.getName());
        user.setAvatar(userUpdateReq.getAvatar());
        return user;
    }


}




